import openslide
import cv2
import numpy as np
from typing import List, Tuple


def extract_tissue_patches_fast(
        file_path: str,
        mask_path: str,
        patch_size: int,
        overlap: int,
        tissue_threshold: float = 0.9
) -> List[Tuple[int, int]]:
    """
    使用积分图(integral image)加速的版本
    适用于需要处理大量patch的场景
    """
    slide = openslide.open_slide(file_path)
    width, height = slide.level_dimensions[0]

    mask = cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE)
    binary_mask = (mask > 1).astype(np.uint8)
    binary_mask = cv2.resize(binary_mask, (width, height), interpolation=cv2.INTER_NEAREST)

    # 使用积分图加速区域求和 - O(1)复杂度
    integral = cv2.integral(binary_mask)

    patch_area_threshold = patch_size * patch_size * tissue_threshold
    step = patch_size - overlap

    detect_points = []

    # 生成所有有效的patch位置
    for h in range(0, height - patch_size + 1, step):
        for w in range(0, width - patch_size + 1, step):
            # 使用积分图快速计算patch区域和
            tissue_sum = (integral[h + patch_size, w + patch_size]
                          - integral[h, w + patch_size]
                          - integral[h + patch_size, w]
                          + integral[h, w])

            if tissue_sum >= patch_area_threshold:
                detect_points.append((w, h))

    # 处理右边界和下边界的patch
    # 右边界
    w = width - patch_size
    for h in range(0, height - patch_size + 1, step):
        tissue_sum = (integral[h + patch_size, w + patch_size]
                      - integral[h, w + patch_size]
                      - integral[h + patch_size, w]
                      + integral[h, w])
        if tissue_sum >= patch_area_threshold and (w, h) not in detect_points:
            detect_points.append((w, h))

    # 下边界
    h = height - patch_size
    for w in range(0, width - patch_size + 1, step):
        tissue_sum = (integral[h + patch_size, w + patch_size]
                      - integral[h, w + patch_size]
                      - integral[h + patch_size, w]
                      + integral[h, w])
        if tissue_sum >= patch_area_threshold and (w, h) not in detect_points:
            detect_points.append((w, h))

    # 右下角
    w = width - patch_size
    h = height - patch_size
    tissue_sum = (integral[h + patch_size, w + patch_size]
                  - integral[h, w + patch_size]
                  - integral[h + patch_size, w]
                  + integral[h, w])
    if tissue_sum >= patch_area_threshold and (w, h) not in detect_points:
        detect_points.append((w, h))

    return detect_points